package cloudUser.config;

import cloudUser.customer.CustomerAccessDeniedHandler;
import cloudUser.customer.JwtTokenAuthFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

/**
 * @program: Smart School
 * @ClassName WebSecurityConfiguration
 * @description: Security 配置类
 * @author: 陈智博
 * @create: 2025-03-27 17:55
 * @Version 1.0
 **/
@Configuration
@EnableWebSecurity
public class SecurityConfig  {

    @Autowired
    private CustomerUserDetailsServiceImpl userDetailsService;

    @Autowired
    private JwtTokenAuthFilter jwtTokenAuthFilter;

    /**
     *  BCryptPasswordEncoder 密码编码器 自定义加密
     * @return 返回 Spring 维护的 Bean 的 BCryptPasswordEncoder
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * AuthenticationManager  认证管理器
     * @param passwordEncoder 密码编码器
     * @return 返回 spring 容器管理的 认证管理器
     * @throws Exception 抛出异常
     */
    @Bean
    public AuthenticationManager authenticationManager(PasswordEncoder passwordEncoder) throws Exception {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(userDetailsService);
        provider.setPasswordEncoder(passwordEncoder);
        return new ProviderManager(provider);
    }

    /**
     * 配置 跨域
     * @return 返回 给spring管理的bean容器
     */
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource =
                new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedOrigins(Arrays.asList("*"));
        corsConfiguration.setAllowedMethods(Arrays.asList("*"));
        corsConfiguration.setAllowedHeaders(Arrays.asList("*"));

        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return urlBasedCorsConfigurationSource;
    }

    /**
     * springsecurity 过滤链 自定义
     * @param http HttpSecurity
     * @return 返回 spring 容器 管理的 过滤链
     * @throws Exception 抛出异常
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        //不通过session获取 securtyContext
        http.sessionManagement((session)->{
            session.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        });

        //禁止csrf跨站访问.
//        http.csrf((csrf)->{
//                csrf.disable()
//            }
//        });

        //配置跨域.
//        http.cors((cors)->{
//            cors.configurationSource(corsConfigurationSource());
//        });

        //添加 Spring Security 拦截规则
        http.authorizeHttpRequests().anyRequest().permitAll()
                .and()
                .cors().configurationSource(corsConfigurationSource())
                .and()
                .csrf().disable();

        // 添加过滤器
        http.addFilterBefore(jwtTokenAuthFilter, UsernamePasswordAuthenticationFilter.class);

        http.exceptionHandling(e->{
            e.accessDeniedHandler(new CustomerAccessDeniedHandler());
        });
        return http.build();
    }


}
